package com.dragon.logical.service.finance.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.common.util.CovertUtil;
import com.dragon.common.util.DateNumUtils;
import com.dragon.common.util.JwtUtil;
import com.dragon.logical.service.customer.CustomerService;
import com.dragon.logical.service.finance.IBillService;
import com.dragon.logical.service.finance.ICustomerPaymentService;
import com.dragon.logical.service.finance.IPlanCollectService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 回款表 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-07-03
 */
@Service
public class CustomerPaymentServiceImpl extends ServiceImpl<CustomerPaymentMapper, CustomerPayment> implements ICustomerPaymentService {

    @Autowired
    CustomerPaymentMapper customerPaymentMapper;
    @Autowired
    PlanCollectMapper planCollectMapper;
    @Autowired
    OtherFileMapper otherFileMapper;
    @Autowired
    CustomerService customerService;
    @Autowired
    PaymentContractMapper paymentContractMapper;
    @Autowired
    ContractMapper contractMapper;
    @Autowired
    BillMapper billMapper;
    @Autowired
    IPlanCollectService planCollectService;
    @Autowired
    IBillService billService;

    @Override
    public Page<CustomerPayment> paymentList(Integer page, Integer limit, String search,Integer type, Integer status, Integer paymentStatus,String startTime, String endTime) {
        Page<CustomerPayment> paymentPage = new Page<>(page, limit);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        QueryWrapper<CustomerPayment> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotEmpty(startTime) || StrUtil.isNotEmpty(endTime)) {
            if (StrUtil.isEmpty(endTime)) {
                endTime = DateUtil.date().toString();
            }
            if (StrUtil.isEmpty(startTime)) {
                startTime = "1999-01-01";
            }
            try {
                df.parse(startTime);
                df.parse(endTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        }
        wrapper.lambda().like(StrUtil.isNotBlank(search),CustomerPayment::getPaymentName,search)
                .eq(status!=null,CustomerPayment::getStatus,status)
                .eq(paymentStatus!=null,CustomerPayment::getPaymentStatus,search)
                .eq(type!=null,CustomerPayment::getPaymentType,type)
                .ge(StrUtil.isNotBlank(startTime), CustomerPayment::getCreateTime, startTime)
                .le(StrUtil.isNotBlank(endTime), CustomerPayment::getCreateTime, endTime);
        return customerPaymentMapper.paymentList(paymentPage, wrapper);
    }

    @Override
    public void addPayment(CustomerPayment payment) {

        Date date = null;
        //自动生成编号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        if (payment.getCreateTime() != null) {
            date = payment.getCreateTime();
        } else {
            date = new Date();
        }
        String code = "HK-" + sdf.format(date);
        String maxCode =  customerPaymentMapper.maxRoundInoutNumber(code);
        String newCode = null;
        if (StrUtil.isEmpty(maxCode)){
            newCode = code + "001";
        }
        else {
            System.out.println(maxCode.length());
            String getMaxCode = maxCode.substring(11, 14);
            newCode = code + DateNumUtils.getNum(getMaxCode);
        }

//        if (payment.getContractId() != null){
//            payment.setPaymentType(1);
//        }
        payment.setStatus(1);
        payment.setRepaymentNum(newCode);
        payment.setCreateTime(DateUtil.date());
        customerPaymentMapper.insert(payment);
        AtomicReference<Double> totalMoney = new AtomicReference<>(0.00);
        //付款子表
        if (payment.getPaymentContracts() != null){
            payment.getPaymentContracts().forEach(paymentContract -> {
                totalMoney.updateAndGet(v -> v + paymentContract.getMoney());
                paymentContract.setPaymentId(payment.getId());
                paymentContract.setCreateTime(DateUtil.date());
                paymentContractMapper.insert(paymentContract);
            });
        }
        payment.setMoney(totalMoney.get());
        customerPaymentMapper.updateById(payment);
        //附件添加
        if(payment.getOtherFileList() != null){
            payment.getOtherFileList().forEach(otherFile -> {
                otherFile.setCorrelationId(payment.getId());
                otherFile.setStreamType(5);
                otherFile.setCreateTime(DateUtil.date());
                otherFileMapper.insert(otherFile);
            });
        }

        if(payment.getStatus() == 1 && payment.getPaymentType()==1){
            planCollectService.generateList(payment,true);
        } else if (payment.getStatus() == 1 && payment.getPaymentType()== 3) {
            billService.updateBillCustomer(payment);
        }

//        AddPageData addPageData = new AddPageData();
//        addPageData.setAdminId(payment.getAdminId());
//        addPageData.setCorrelationId(payment.getId());
//        addPageData.setWorkflowJson(payment.getWorkflowJsonList());
//        addPageData.setStreamType(5);
//        addPageData.setTitle(payment.getPaymentName());
//        addPageData.setExempt(payment.getExempt()==null?0:1);
//        return addPageData;

    }

    @Override
    public void updatePayment(CustomerPayment payment) {
        CustomerPayment customerPayment = customerPaymentMapper.selectById(payment.getId());
        if (customerPayment == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        payment.setUpdateTime(DateUtil.date());
        customerPaymentMapper.updateById(payment);
        if (payment.getOtherFileList() != null){
            payment.getOtherFileList().forEach(otherFile -> {
                otherFileMapper.update(otherFile,new QueryWrapper<OtherFile>().lambda()
                        .eq(OtherFile::getCorrelationId,payment.getId()).eq(OtherFile::getStreamType,5));
            });
        }
    }

    @Override
    public void deletePayment(Integer id) {
        CustomerPayment payment = customerPaymentMapper.selectById(id);
        if (payment == null) {
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        customerService.deleteThorough(5,id);
        customerPaymentMapper.deleteById(id);
    }

    @Override
    public List<CustomerPayment> selectByContractId(Integer contractId) {
        return customerPaymentMapper.selectCpByContractId(contractId);
    }

    @Override
    public CustomerPayment detailById(Integer id) {
        CustomerPayment customerPayment = customerPaymentMapper.selectByPaymentId(id);
        if(customerPayment.getPaymentType()==1){
            List<PaymentContract> paymentContracts = paymentContractMapper.selectByPaymentId(customerPayment.getId());
            if (paymentContracts != null){
                customerPayment.setPaymentContracts(paymentContracts);
            }
        }
        //客户收款
        if(customerPayment.getPaymentType() == 3){
            List<PaymentContract> paymentContracts = paymentContractMapper.selectContractByPaymentId(customerPayment.getId());
            if (paymentContracts != null){
                customerPayment.setPaymentContracts(paymentContracts);
            }
        }
        List<OtherFile> otherFiles = otherFileMapper.selectList(new QueryWrapper<OtherFile>().lambda()
                .eq(OtherFile::getCorrelationId, id).eq(OtherFile::getStreamType, 5));
        if (otherFiles != null){
            customerPayment.setOtherFileList(otherFiles);
        } else {
            customerPayment.setOtherFileList(new ArrayList<>());
        }
        return customerPayment;
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public List<PlanCollect> selectMoneyByPlanIdAndControllerId(String planIds){
        List<Integer> planIntegerIds = CovertUtil.covertIntegerList(planIds);
        LambdaQueryWrapper<PlanCollect> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(PlanCollect::getId,planIntegerIds);
        List<PlanCollect> planCollects = planCollectMapper.selectList(queryWrapper);
        if(planCollects.size() == 0){
            throw new CustomException(ResultCode.DATA_NOT_FOUND);
        }
        planCollects.forEach(planCollect -> {

            Contract contract = contractMapper.selectById(planCollect.getContractId());

            planCollect.setTractName(contract.getName());

            Double money = Double.valueOf(0);
            //查询单条的在审金额
            List<PaymentContract> paymentContracts = paymentContractMapper.selectMoneyByContractId(planCollect.getId(),planCollect.getContractId());
            if(paymentContracts!=null &&paymentContracts.size()!=0) {
                money = paymentContracts.stream().map(PaymentContract::getMoney).reduce((a,b)-> a+b ).get();
            }
            planCollect.setAuditMoney(money);
        });
        return planCollects;
    }



    @Override
    public Map<String, Object> getAmount(Integer adminId, String year, String yearMonth) {
        Map<String, Object> map = new HashMap<>();
        Double aDouble = customerPaymentMapper.selectReceivables(adminId,year,yearMonth);
        Double bDouble = customerPaymentMapper.selectPaid(adminId, year, yearMonth);
        if (aDouble == null){
            aDouble = 0.00;
        }
        if (bDouble == null){
            bDouble = 0.00;
        }
        map.put("应收",aDouble);
        map.put("实收",bDouble);
        return map;

    }

    @Override
    public Map<String, Object> getReceivablesMoney(Integer adminId, String year) {
        Map<String, Object> map = customerPaymentMapper.selectGetReceivablesMoney(adminId, year);
        return map;
    }

    @Override
    public Map<String, Object> getPaidMoney(Integer adminId, String year, Integer type) {
        Map<String, Object> map = customerPaymentMapper.selectGetPaidMoney(adminId, year,type);
        return map;
    }

    @Override
    public Map<String, Object> getReceivablesPercentage(Integer adminId, String year ,Integer type) {
        //获取应收
        Double receivables = 0.00;
        Double paid = 0.00;
        List<PlanCollect> planCollects = planCollectMapper.selectList(new QueryWrapper<PlanCollect>()
                .lambda().eq(adminId != null, PlanCollect::getAdminId, adminId)
                .apply(StrUtil.isNotBlank(year)," date_format(create_time,'%Y')  = '" + year + "'"));
        for (PlanCollect planCollect : planCollects) {
            receivables += planCollect.getPlanMoney();
        }

        List<CustomerPayment> customerPayments = customerPaymentMapper.selectList(new QueryWrapper<CustomerPayment>()
                .lambda().eq(adminId != null, CustomerPayment::getAdminId, adminId)
                .eq(type != null,CustomerPayment::getRepaymentType,type)
                .apply(StrUtil.isNotBlank(year)," date_format(create_time,'%Y')  = '" + year + "'"));
        for (CustomerPayment customerPayment : customerPayments) {
            paid += customerPayment.getMoney();
        }
        Double percentage = Double.valueOf(0);
        if (paid != 0 || receivables != 0){
            percentage = ( paid / receivables ) * 100;
        }
        DecimalFormat df = new DecimalFormat("#.00");
        Map<String, Object> map = new HashMap<>();
        map.put("实收占比：",percentage);
        return map;
    }

    @Override
    public Map<String, Object> currenDate(HttpServletRequest request, Integer adminId) {
        Integer isAdmin = JwtUtil.getIsAdmin(request);
        String authCode = JwtUtil.getAuthCode(request);
        String departmentIds = JwtUtil.getDepartmentIds(request);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        String time = sdf.format(new Date());
        Map<String, Object> map = new HashMap<>();
        List<CustomerPayment> customerPayments = null;
        //判断是否是管理员
        if (isAdmin == 1) {
            customerPayments = customerPaymentMapper.selectListByPermissions(time, null, null);
        } else if (authCode.equals("1")) {
            customerPayments = customerPaymentMapper.selectListByPermissions(time,adminId,null);
            //判断是否本人
        } else if (authCode.equals("2") || authCode.equals("3") || authCode.equals("4")) {
            // 判断部门权限
            List<String> departmentSet = Arrays.asList(departmentIds.split(","));
            customerPayments = customerPaymentMapper.selectListByPermissions(time,null,departmentSet);
        }
        List<CustomerPayment> list = customerPaymentMapper.selectListByPermissions(null, null, null);
        AtomicReference<Double> monthMoney = new AtomicReference<>(0.0);
        AtomicReference<Double> amount = new AtomicReference<>(0.0);
        list.forEach(payment -> {
            amount.updateAndGet(v -> v + payment.getMoney());
        });
        customerPayments.forEach(customer -> {
            monthMoney.updateAndGet(v -> v + customer.getMoney());
        });
        map.put("amount", amount.get());
        map.put("monthMoney", monthMoney.get());
        return map;
    }

    @Override
    public void antiAudit(Integer correlationId) {
        CustomerPayment payment = customerPaymentMapper.selectById(correlationId);
        payment.setStatus(0);
        customerPaymentMapper.updateById(payment);
    }

    @Override
    public Double selectMoneyByBillId(Integer billId) {
        QueryWrapper<PaymentContract> wrapper = new QueryWrapper<>();
        wrapper.lambda().select(PaymentContract::getPaymentId).eq(PaymentContract::getBillId, billId);
        List<PaymentContract> paymentContracts = paymentContractMapper.selectList(wrapper);
        AtomicReference<Double> money = new AtomicReference<>(Double.valueOf(0));
        paymentContracts.forEach(paymentContract -> {
            LambdaQueryWrapper<CustomerPayment> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CustomerPayment::getId,paymentContract.getPaymentId())
                    .eq(CustomerPayment::getStatus , 0);
            CustomerPayment customerPayment = customerPaymentMapper.selectOne(queryWrapper);
            if(customerPayment != null){
                money.updateAndGet(v -> v + customerPayment.getMoney());
            }
        });
        return money.get();
    }

    @Override
    public Double selectMoneyByPlanId(Integer planId,Integer contractId) {
        Double money = Double.valueOf(0);
        //查询单条的在审金额
        List<PaymentContract> paymentContracts = paymentContractMapper.selectMoneyByContractId(planId,contractId);
        if(paymentContracts!=null &&paymentContracts.size()!=0) {
            money = paymentContracts.stream().map(PaymentContract::getMoney).reduce((a,b)-> a+b ).get();
        }
        return money;
    }


    @Override
    public Page<PaymentContract> selectPlanCollectDetail(Integer planId, Integer page, Integer limit){
        Page<PaymentContract> paymentPage = new Page<>(page,limit);
        QueryWrapper<PaymentContract> lambdaQueryWrapper = new QueryWrapper<>();
        lambdaQueryWrapper.lambda().eq(PaymentContract::getPlanId,planId)
                .orderByDesc(PaymentContract::getCreateTime);
        Page<PaymentContract> paymentContracts = paymentContractMapper.selectpageByWarpper(paymentPage,lambdaQueryWrapper);
        return paymentContracts;
    }

    @Override
    public Page<CustomerPayment> selectCustomerPaymentDetail(Integer billId,Integer page,Integer limit){
        Page<CustomerPayment> customerPaymentPage = new Page<>(page,limit);
        //查询收款子表信息 获取主表id列表
        List<PaymentContract> paymentContracts = paymentContractMapper.selectList(new QueryWrapper<PaymentContract>()
                .lambda()
                .eq(PaymentContract::getBillId, billId));
        if(paymentContracts.size() == 0){
            return null;
        }
        List<Integer> paymentIds = paymentContracts.stream().map(PaymentContract::getPaymentId).collect(Collectors.toList());
        //根据子表查询 主表分页列表
        QueryWrapper<CustomerPayment> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(CustomerPayment::getId,paymentIds);
        Page<CustomerPayment> paymentPage = customerPaymentMapper.selectPage(customerPaymentPage,queryWrapper);
        return paymentPage;
    }

    @Override
    public Map<String,Object> selectListStatistics(){
        return customerPaymentMapper.selectListStatistics();
    }

    @Override
    public LinkedHashMap<String, Object> customerPaymentMonthlyStatistics(String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy");
        }
        return customerPaymentMapper.customerPaymentMonthlyStatistics(time);
    }
}
